home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / mail / mailleds.93 / mailleds / mailleds-0.93 / mailleds.c < prev    next >
C/C++ Source or Header  |  1996-05-14  |  9KB  |  473 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.  
  13.  
  14.  
  15.  
  16.  
  17.  
  18.  
  19.  
  20.  
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36. /* 
  37.  *  mailleds - Check for new mail, blinking keyboard leds when it arrives
  38.  *  Copyright (C) 1996 Benjamin Osheroff 
  39.  *
  40.  *  This program is free software; you can redistribute it and/or modify
  41.  *  it under the terms of the GNU General Public License as published by
  42.  *  the Free Software Foundation; either version 2 of the License, or
  43.  *  (at your option) any later version.
  44.  *
  45.  *  This program is distributed in the hope that it will be useful,
  46.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  47.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  48.  *  GNU General Public License for more details.
  49.  *
  50.  *  You should have received a copy of the GNU General Public License
  51.  *  along with this program; if not, write to the Free Software
  52.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  53.  * 
  54.  *
  55.  *  Author: Benjamin Osheroff (mtr@ratbert.bagel.org)
  56.  *  106 Meernaa Ave.
  57.  *  Fairfax, CA 94930
  58.  *
  59.  *
  60.  */
  61.  
  62. #include <stdio.h>
  63. #include <stdlib.h>
  64. #include <fcntl.h>
  65. #include <errno.h>
  66. #include <getopt.h>
  67. #include <signal.h>
  68. #include <time.h>
  69. #include <paths.h>
  70. #include <pwd.h>
  71. #include <string.h>
  72. #include <ctype.h>
  73. #include <unistd.h>
  74. #include <sys/ioctl.h>
  75. #include <sys/stat.h>
  76. #include <linux/kd.h>
  77. #include <utmp.h>
  78.  
  79. #ifdef X_SUPPORT
  80. #include <X11/X.h>
  81. #include <X11/Xlib.h>
  82. #endif
  83.  
  84. #include "config.h"
  85. #include "mailleds.h"
  86.  
  87. sig_atomic_t exit_now = 0;
  88. char opt_a, opt_h, opt_q, opt_l, opt_t, opt_u, opt_x, *opt_m, *opt_d;
  89. char *pid_filename;
  90. char *username;
  91. int kbd_leds = 0x0;
  92. int port_leds = 0x0;
  93.  
  94. /* array of open file descriptors of ttys whose leds must be flashed */
  95. int ct[MAX_CONSOLES];
  96.  
  97. /* X Display whose leds must be flashed */
  98. #ifdef X_SUPPORT
  99. Display *dpy;
  100. #endif
  101.  
  102. /* array of X leds that are to be flashed */
  103. int x_leds[3];
  104. int uid, euid, pid;
  105.  
  106. void usage(void)
  107. {
  108.     fprintf(stderr, "usage: mailleds [ -afhkqtx ] [ -m filename ] [ -l [cns] ] [ -d dpy ]\n");
  109.     fprintf(stderr, "Options:\n");
  110.     fprintf(stderr, "-a, --answering-machine  : blink number of messages on led\n");
  111.     fprintf(stderr, "-h, --help               : brings up this help screen\n");
  112.     fprintf(stderr, "-k, --kill               : kills a running mailleds daemon\n");
  113.     fprintf(stderr, "-q, --quiet              : die quietly if another mailleds process exists\n");
  114.     fprintf(stderr, "-t, --ttys               : specifies that mailleds should flash the vt's leds.\n");
  115.     fprintf(stderr, "                           (This is the default if -d is not specified but keyboard LEDs are.)\n");
  116.     fprintf(stderr, "--version                : displays version number\n");
  117.     fprintf(stderr, "-u, --user <user>        : runs mailleds as if you were <user>.  You must be root to specify this.\n");
  118.     fprintf(stderr, "-l, --leds [cnsp<number>]\n");
  119.     fprintf(stderr, "                         : c, n, and s are keyboard LEDs mailleds will blink.\n");
  120. #ifdef PARALLEL_SUPPORT
  121.     fprintf(stderr, "                         : p<number> corresponds to LEDs hooked up to a port.\n");
  122. #endif
  123. #ifdef X_SUPPORT
  124.     fprintf(stderr, "-x                       : flash the leds on a X display.\n");
  125.     fprintf(stderr, "-d, --display dpy        : tells mailleds which X display to use.");
  126.     fprintf(stderr, "  Optional, defaults to current display.\n");
  127. #endif
  128.     fprintf(stderr, "-m, --mailbox filename   : use 'filename' as a mailbox file\n");
  129.  
  130. }
  131.  
  132. static struct option long_options[] =
  133. {
  134.     {"message-count", 0, 0, 'a'},
  135.     {"leds", 1, 0, 'l'},
  136.     {"help", 0, 0, 'h'},
  137.     {"display", 0, 0, 'd'},
  138.     {"kill", 0, 0, 'k'},
  139.     {"quiet", 0, 0, 'q'},
  140.     {"version", 0, 0, 'v'},
  141.     {"mailbox", 1, 0, 'm'},
  142.     {"ttys", 0, 0, 't'},
  143.     {"user", 1, 0, 'u'},
  144.     {0, 0, 0, 0}
  145. };
  146.  
  147. void parse_argv(argc, argv)
  148. int argc;
  149. char *argv[];
  150. {
  151.     int other_process_pid;
  152.     int index = 0;
  153.     char opt;
  154.     char *program;
  155.     struct passwd *pass_info;
  156.     kbd_leds = 0x00;
  157.     port_leds = 0x00;
  158.  
  159.     /* first, parse the name given. */
  160.  
  161.     program = rindex(*argv, '/');
  162.     if (program == NULL) {
  163.         program = *argv;
  164.     } else
  165.         program++;
  166.  
  167.     if (strcmp(program, "xmailleds") == 0)
  168.         opt_x = 1;
  169.  
  170.     while (1) {
  171.         opt = getopt_long(argc, argv, "ahkqxtl:m:d:u:", long_options, &index);
  172.         if (opt == -1)
  173.             break;
  174.  
  175.         switch (opt) {
  176.         case 'a':
  177.             opt_a = 1;
  178.             break;
  179.  
  180.         case 'h':
  181.             usage();
  182.             exit(0);    /* printing help was succesful */
  183.             break;
  184.  
  185.         case 'k':
  186.             set_pidfilename();
  187.             other_process_pid = get_pid_from_file(pid_filename);
  188.             if (other_process_pid) {
  189.                 if (kill(other_process_pid, SIGTERM)) {
  190.                     perror("mailleds");
  191.                     exit(-2);
  192.                 }
  193.                 fprintf(stderr, "mailleds: process %d killed sucessfully\n", other_process_pid);
  194.                 exit(0);
  195.             } else {
  196.                 fprintf(stderr, "mailleds: no process running for %s\n", username);
  197.                 exit(1);
  198.             }
  199.             break;
  200.  
  201.         case 'q':
  202.             opt_q = 1;
  203.             break;
  204.  
  205.         case 'v':
  206.             fprintf(stderr, "mailleds version %s\n", VERSION);
  207.             exit(0);
  208.             break;
  209.  
  210.         case 'm':
  211.             opt_m = strdup(optarg);
  212.             break;
  213.  
  214.         case 't':
  215.             opt_t = 1;
  216.             break;
  217.  
  218.         case 'x':
  219.             opt_x = 1;
  220.             break;
  221.  
  222.         case 'u':
  223.             if (uid != 0) {
  224.                 fprintf(stderr, "mailleds: only root can specify -u\n");
  225.                 exit(-1);
  226.             }
  227.             /* here we effectively become the user in -u */
  228.             free(username);
  229.             username = strdup(optarg);
  230.             pass_info = getpwnam(username);
  231.             uid = pass_info->pw_uid;
  232.             opt_u = 1;
  233.             break;
  234.  
  235.         case 'd':
  236.             opt_d = strdup(optarg);
  237.             opt_x = 1;
  238.             break;
  239.  
  240.         case 'l':
  241.             while (*optarg && *optarg != ' ') {
  242.                 switch (*optarg) {
  243.                 case 'n':
  244.                     kbd_leds |= LED_NUM;
  245.                     break;
  246.  
  247.                 case 'c':
  248.                     kbd_leds |= LED_CAP;
  249.                     break;
  250.  
  251.                 case 's':
  252.                     kbd_leds |= LED_SCR;
  253.                     break;
  254.  
  255. #ifdef PARALLEL_SUPPORT
  256.                 case 'p':
  257.                     switch (*++optarg) {
  258.                     case '1':
  259.                         port_leds |= PORT_LED_1;
  260.                         break;
  261.                     case '2':
  262.                         port_leds |= PORT_LED_2;
  263.                         break;
  264.                     case '3':
  265.                         port_leds |= PORT_LED_3;
  266.                         break;
  267.                     case '4':
  268.                         port_leds |= PORT_LED_4;
  269.                         break;
  270.                     case '5':
  271.                         port_leds |= PORT_LED_5;
  272.                         break;
  273.                     case '6':
  274.                         port_leds |= PORT_LED_6;
  275.                         break;
  276.                     case '7':
  277.                         port_leds |= PORT_LED_7;
  278.                         break;
  279.                     case '8':
  280.                         port_leds |= PORT_LED_8;
  281.                         break;
  282.                     default:
  283.                         fprintf(stderr, "mailleds: no such led p%c", *optarg);
  284.                         exit(-1);
  285.                     }
  286.                     break;
  287. #endif                /* PARALLEL_SUPPORT */
  288.                 default:
  289.                     fprintf(stderr, "mailleds: Unknown LED '%c'\n", *optarg);
  290.                     exit(-1);
  291.                 }
  292.                 optarg++;
  293.             }
  294.             break;
  295.  
  296.         case '?':
  297.             usage();
  298.             exit(-1);
  299.             break;
  300.  
  301.         case ':':
  302.             usage();
  303.             exit(-1);
  304.             break;
  305.         }
  306.     }
  307.  
  308.     /* default behavior */
  309.     if (!opt_t && !opt_x && !port_leds)
  310.         opt_t = 1;
  311.  
  312.     if (!opt_m)
  313.         opt_m = get_mailfile();
  314.  
  315.     if (!kbd_leds && (opt_x || opt_t))
  316.         kbd_leds = DEF_KBD_LEDS;
  317.  
  318.     if (kbd_leds && !opt_x && !opt_t)
  319.         opt_t = 1;
  320.  
  321.     if (!kbd_leds && !port_leds) {
  322.         kbd_leds = DEF_KBD_LEDS;
  323.         port_leds = DEF_PORT_LEDS;
  324.     }
  325. #ifdef X_SUPPORT
  326.     if (opt_x)
  327.         get_X_leds_from_kbd_leds(kbd_leds);
  328. #endif
  329.  
  330. }
  331.  
  332. void fatal_error_signal(int sig)
  333. {
  334.     exit_now = 1;
  335. }
  336.  
  337. void exit_cleanly()
  338. {
  339.     setreuid(uid, euid);
  340.     unlink(pid_filename);
  341.     exit(0);
  342. }
  343.  
  344. void exit_fatal(const char *reason)
  345. {
  346.     setreuid(uid, euid);
  347.     unlink(pid_filename);
  348.     fprintf(stderr, "mailleds: %s\n", reason);
  349.     exit(1);
  350. }
  351.  
  352. void set_up_signals()
  353. {
  354.     signal(SIGINT, fatal_error_signal);
  355.     signal(SIGTERM, fatal_error_signal);
  356. }
  357.  
  358. time_t
  359. get_time_of(filename)
  360. char *filename;
  361. {
  362.     static struct stat i;
  363.     if (stat(filename, &i))
  364.         return (rand());    /* If unable to stat, this forces the mailfile check / wait functions to kick in. */
  365.     return (i.st_ctime);
  366. }
  367.  
  368. void stat_error(filename)
  369. char *filename;
  370. {
  371.     char *msg;
  372.     msg = (char *) xmalloc(strlen("mailleds: ") + strlen(filename) + 1);
  373.     sprintf(msg, "mailleds: %s", filename);
  374.     perror(msg);
  375.     exit_fatal("File access error");
  376. }
  377.  
  378. int main(argc, argv)
  379. int argc;
  380. char *argv[];
  381. {
  382.     FILE *mailbox;
  383.     time_t newmod;
  384.     struct passwd *uinfo;
  385.  
  386.     int mail = 0;
  387.     time_t lastmod = 0;
  388.  
  389.     uid = getuid();
  390.     euid = geteuid();
  391.     if (!opt_u) {
  392.         uinfo = getpwuid(uid);
  393.         username = strdup(uinfo->pw_name);
  394.     }
  395.     /* don't need to know pid to know pid filename */
  396.     parse_argv(argc, argv);
  397.     set_pidfilename();
  398.  
  399.     if (!opt_x)
  400.         pid_check();
  401.  
  402. #ifndef DEBUG
  403.     switch (fork()) {
  404.     case -1:        /* Cannot fork */
  405.         perror("fork");
  406.         exit(1);
  407.     case 0:        /* Son process */
  408.         break;
  409.     default:        /* Father process */
  410.         exit(0);
  411.     }
  412. #endif
  413.  
  414.     if (!opt_x) {
  415.         pid = getpid();
  416.         write_pidfile();
  417.         detach_from_tty();
  418.     }
  419. #ifdef PARALLEL_SUPPORT
  420.     if (port_leds) {
  421.         if ((ioperm(LPT_PORT, 1, 1)) == -1) {
  422.             fprintf(stderr, "unable to set permissions on port 0x%x\n",
  423.                 LPT_PORT);
  424.             perror("mailleds");
  425.             exit(1);
  426.         }
  427.     }
  428. #endif
  429.  
  430.     setreuid(euid, uid);
  431.     set_up_signals();
  432.     while (!exit_now) {
  433.         newmod = get_time_of(opt_m);
  434.         if (lastmod != newmod) {
  435.             mailbox = open_mailbox_file(opt_m);
  436.             mail = count_mail(mailbox);
  437.             lastmod = newmod;
  438.             fclose(mailbox);
  439.         }
  440.         if (kbd_leds) {
  441.             if (opt_t)
  442.                 make_tty_array();
  443.  
  444. #ifdef X_SUPPORT
  445.             if (opt_x) {
  446.                 dpy = XOpenDisplay(opt_d);
  447.                 if (dpy == (Display *) NULL)
  448.                     exit_fatal("Cannot open Display");
  449.                 XCloseDisplay(dpy);
  450.             }
  451. #endif
  452.             if (!port_leds && opt_t && *ct == -1 && !opt_u)        /* we never exit with port_leds */
  453.                 exit_fatal("Couldn't locate your login tty");
  454.         }
  455.         if (mail) {
  456.             if (!opt_x)
  457.                 setreuid(uid, euid);
  458.             if (opt_a) {
  459.                 blink_x(BLINK_TIME_ON, BLINK_TIME_OFF, mail);
  460.                 usleep(TIME_BETWEEN_COUNTS);
  461.             } else {
  462.                 blink_once(BLINK_TIME_ON, BLINK_TIME_OFF);
  463.                 usleep(TIME_BETWEEN_COUNTS);
  464.             }
  465.             if (!opt_x)
  466.                 setreuid(euid, uid);
  467.         } else {
  468.             sleep(INTERVAL_BETWEEN_CHECKS);
  469.         }
  470.     }
  471.     exit_cleanly();
  472. }
  473.